<template>
	<view class="vk-data-canvas-poster">
		<view class="canvas-hide">
			<canvas :id="canvasID" :canvas-id="canvasID" :style="canvasStyleCom"></canvas>
		</view>
	</view>
</template>

<script>
	/**
	 * vk-data-canvas-poster canvas海报绘制
	 * @example <vk-data-canvas-poster ref="canvasPoster"></vk-data-canvas-poster>
	 */
	export default {
		name: "vk-data-canvas-poster",
		//emits: ["click"],
		props: {

		},
		data: function() {
			return {
				canvasID: "vk-data-canvas-poster-" + Math.floor(Math.random() * 1000000),
				canvasWidth: 0, // canvas宽度
				canvasHeight: 0, // canvas高度
				loading: false, // 是否绘制中
				ctx: null, // canvas上下文
				canvasImage: "", // canvas转图片后的base64值
				options: {}
			};
		},
		mounted() {

		},
		methods: {
			/**
			 * draw 绘制海报
			 * @property {Array} steps 绘制步骤
			 * @property {String} background canvas背景颜色（默认#ffffff）
			 * @property {Number} pixelRatio 像素比（默认2）
			 * @property {Number} width canvas宽度（默认500）
			 * @property {Number} height canvas高度（默认900）
			 */
			async draw(options = {}) {
				options = Object.assign({
					steps: [],
					background: "#ffffff",
					pixelRatio: 2, // 一般无需修改此值
					width: 500, // canvas宽度
					height: 900, // canvas高度
					quality: 1, // 图片质量
				}, options);
				this.options = options;
				try {
					let { steps } = this.options;
					if (this.options.title) {
						uni.showLoading({
							title: this.options.title,
							mask: true
						});
					}
					this.createCanvasContext();
					for (let i = 0; i < steps.length; i++) {
						let step = steps[i];
						if (step.type === "rect") {
							this.drawRect(step.bg, step.x, step.y, step.w, step.h);
						} else if (step.type === "image") {
							await this.drawImage(step.src, step.x, step.y, step.w, step.h, step.imageType);
						} else if (step.type === "text") {
							this.drawText(step.text, step.x, step.y, step.size, step.color, step.align);
						} else if (step.type === "line") {
							this.drawLine(step.x1, step.y1, step.x2, step.y2, step.color);
						}
					}
					//延迟后渲染至canvas上
					setTimeout(() => {
						this.ctx.draw(true, res => {
							this.canvasToTempFilePath();
							this.loading = false;
							if (this.options.title) uni.hideLoading();
						});
					}, 600);
				} catch (err) {
					this.loading = false;
					if (this.options.title) uni.hideLoading();
					if (typeof this.options.fail === "function") {
						this.options.fail(err);
					}
					if (typeof this.options.complete === "function") {
						this.options.complete(err);
					}
				}
			},
			createCanvasContext() {
				let { pixelRatio, width, height, background } = this.options;
				let ctx = uni.createCanvasContext(this.canvasID, this);
				this.canvasWidth = width * pixelRatio;
				this.canvasHeight = height * pixelRatio;
				ctx.setFillStyle(background); //canvas背景颜色
				ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight); //canvas画布大小
				this.ctx = ctx;
				return ctx;
			},
			// 画矩形
			drawRect(bg, x, y, w, h) {
				let { ctx } = this;
				let { pixelRatio } = this.options;
				ctx.setFillStyle(bg);
				ctx.fillRect(x * pixelRatio, y * pixelRatio, w * pixelRatio, h * pixelRatio);
			},
			// 画线
			drawLine(x1, y1, x2, y2, color) {
				let { ctx } = this;
				let { pixelRatio } = this.options;
				ctx.strokeStyle = color;
				ctx.moveTo(x1 * pixelRatio, y1 * pixelRatio);
				ctx.lineTo(x2 * pixelRatio, y2 * pixelRatio);
				ctx.stroke();
			},
			// 画图片
			async drawImage(src, x, y, w, h, type = "square") {
				let { ctx } = this;
				let { pixelRatio } = this.options;
				if (src.indexOf("https://") === 0) {
					let width = Math.floor(w * pixelRatio);
					let height = Math.floor(h * pixelRatio);
					src += src.indexOf("?") === -1 ? "?" : "&";
					// 此为七牛云的图片处理参数，其他云存储可自行修改
					src += `imageMogr2/thumbnail/!${width}x${height}r|imageMogr2/gravity/Center/crop/${width}x${height}`;
				}
				try {
					let imageInfo = await this.getImageInfo(src);
					if (type === "circle") {
						// 画圆形
						ctx.save(); // 保存当前绘图状态
						ctx.beginPath();
						ctx.arc(x * pixelRatio + w * pixelRatio / 2, y * pixelRatio + h * pixelRatio / 2, w * pixelRatio / 2, 0, Math.PI * 2, false);
						ctx.clip(); // 裁剪区域为圆形
						ctx.drawImage(imageInfo.path, x * pixelRatio, y * pixelRatio, w * pixelRatio, h * pixelRatio);
						ctx.restore(); // 恢复之前保存的绘图状态
					} else {
						// 画方形
						ctx.drawImage(imageInfo.path, x * pixelRatio, y * pixelRatio, w * pixelRatio, h * pixelRatio);
					}
				} catch (err) {}
			},
			// 画文本
			async drawText(text, x, y, size, color, textAlign) {
				let { ctx } = this;
				let { pixelRatio } = this.options;
				if (size) ctx.setFontSize(size * pixelRatio);
				if (color) ctx.setFillStyle(color);
				if (textAlign) ctx.textAlign = textAlign;
				ctx.fillText(text, x * pixelRatio, y * pixelRatio);
			},
			// 获取可用于画布的图片信息
			async getImageInfo(src) {
				let vk = uni.vk;
				let promise = new Promise(async (resolve, reject) => {
					try {
						if (!src) {
							console.log("src不能为空");
							reject();
						} else {
							if (src.indexOf("base64,") > -1) {
								let file = await vk.pubfn.base64ToFile({
									base64: src
								});
								src = file.path;
							}
							uni.getImageInfo({
								src: src,
								success(image) {
									resolve(image);
								},
								fail(err) {
									console.error("getImageInfo-err", err, "src", src);
									reject(err);
								}
							});
						}
					} catch (err) {
						console.error("getImageInfo异常", err);
						reject();
					}
				});
				promise.catch(err => {
					vk.hideLoading();
				});
				return promise;
			},
			// 画布转临时图片
			canvasToTempFilePath() {
				uni.canvasToTempFilePath({
						canvasId: this.canvasID,
						quality: this.options.quality || 1,
						destWidth: this.options.width * this.options.pixelRatio,
						destHeight: this.options.height * this.options.pixelRatio,
						success: res => {
							this.canvasImage = res.tempFilePath;
							if (typeof this.options.success === "function") {
								this.options.success({
									base64: this.canvasImage,
								});
							}
							if (typeof this.options.complete === "function") {
								this.options.complete(res);
							}
						},
						fail: err => {
							if (typeof this.options.fail === "function") {
								this.options.fail(err);
							}
							if (typeof this.options.complete === "function") {
								this.options.complete(err);
							}
						}
					},
					this
				);
			},
			// 保存到手机相册
			saveImageToPhotosAlbum() {
				let vk = uni.vk;
				uni.saveImageToPhotosAlbum({
					filePath: this.canvasImage,
					success: res => {
						vk.toast("已保存到相册", "none");
					}
				});
			}
		},
		// 监听属性
		watch: {

		},
		// 计算属性
		computed: {
			canvasStyleCom() {
				return {
					width: this.canvasWidth + 'px',
					height: this.canvasHeight + 'px'
				}
			}
		}
	};
</script>

<style lang="scss" scoped>
	.vk-data-canvas-poster {
		.canvas-hide {
			position: absolute;
			top: -100000px;
			width: 0;
			height: 0;
		}
	}
</style>
